﻿using System;
using System.Linq;
using System.Web;
using System.Collections.Generic;
using ManagedServices.UI.Web.Models;
using ManagedServices.DataTransferObjects;
using System.Data.Linq;
using ManagedServices.Persistence;
using System.Configuration;

namespace ManagedServices.UI.Web.Controllers
{
    public class DTOConverter
    {
        private static string _messageBoxConnectionString;
        private static string _metaStoreConnectionString;

        static DTOConverter()
        {
            _messageBoxConnectionString = ConfigurationManager.ConnectionStrings["messageBoxConnectionString"].ConnectionString;
            _metaStoreConnectionString  = ConfigurationManager.ConnectionStrings["metaStoreConnectionString"].ConnectionString;
        }

        public static void PersistSubServiceMetadataModel(SubServiceMetadataModel instance, Func<string, System.Data.Linq.Binary> GetDependencyBinary)
        {
            MetaStoreDataContext dc = new MetaStoreDataContext(_metaStoreConnectionString);

            SubServiceRunConfig config      = new SubServiceRunConfig();
            config.SubServiceRunConfigID    = Guid.NewGuid();
            config.CreatedBy                = Guid.Empty;
            config.CreatedOn                = DateTime.Now;
            config.IsMasterRunConfig        = true;
            config.RunMode                  = ReadOnlyDataCollection.StartModes.Where((mode) => mode.Name == instance.RunConfig.RunMode).First().Code;
            config.RunConfig                = instance.RunConfig.RunConfig;
            dc.SubServiceRunConfigs.InsertOnSubmit(config);

            SubService subServiceInstance               = new SubService();
            subServiceInstance.SubServiceID             = Guid.NewGuid();
            subServiceInstance.SubServiceName           = instance.SubServiceName;
            subServiceInstance.SubServiceDescription    = instance.SubServiceDescription;
            subServiceInstance.UniqeURN                 = instance.UniqueURN;
            subServiceInstance.NumberOfInstances        = 0;
            subServiceInstance.AssociatedIdentityID     = Guid.Empty;
            subServiceInstance.ContainerServiceID       = Guid.Empty;
            subServiceInstance.CreatedBy                = Guid.Empty;
            subServiceInstance.CreatedOn                = DateTime.Now;
            subServiceInstance.SubServiceRunConfigID    = config.SubServiceRunConfigID;
            dc.SubServices.InsertOnSubmit(subServiceInstance);

            foreach (SubscriptionModel item in instance.Subscriptions)
            {
                Subscription subs       = new Subscription();
                subs.CreatedBy          = Guid.Empty;
                subs.CreatedOn          = DateTime.Now;
                subs.MessageRootElement = item.MessageRootName;
                subs.MessageNamespace   = item.MessageNamespace;
                subs.SubscriptionID     = Guid.NewGuid();
                subs.SubServiceID       = subServiceInstance.SubServiceID;
                dc.Subscriptions.InsertOnSubmit(subs);
            }

            
            foreach (var item in instance.Dependencies)
            {
                Dependency dep          = new Dependency();
                dep.CreatedBy           = Guid.NewGuid();
                dep.CreatedOn           = DateTime.Now;
                dep.DependencyID        = Guid.NewGuid();
                dep.DependencyName      = item.Name;
                dep.DependencyType      = ReadOnlyDataCollection.DependencyTypes.Where(depType => depType.Name.ToLower() == item.DependencyType.ToLower()).First().Code;
                dep.DependencyRawData   = GetDependencyBinary(item.Name);
                dep.Version             = instance.Version;
                dep.SubServiceID        = subServiceInstance.SubServiceID;
                dc.Dependencies.InsertOnSubmit(dep);
            }
            dc.SubmitChanges();
            dc.Dispose();
        }

        internal static SubServiceMetadataModel[] GetSubServices()
        {
            MetaStoreDataContext dc = new MetaStoreDataContext(_metaStoreConnectionString);
            SubService[] subServices = (from s in dc.SubServices
                                        select s).ToArray();
            dc.Dispose();
            List<SubServiceMetadataModel> subMetaModels = new List<SubServiceMetadataModel>();
            foreach (var item in subServices)
            {
                SubServiceMetadataModel subMetaModel = new SubServiceMetadataModel() 
                { 
                    SubServiceID    = item.SubServiceID.ToString(),
                    SubServiceName  = item.SubServiceName,
                    SubServiceDescription = item.SubServiceDescription,
                    UniqueURN       = item.UniqeURN
                };
                subMetaModels.Add(subMetaModel);
            }
            return subMetaModels.ToArray();
        }

        internal static SubServiceMetadataModel GetSubService(Guid ssID)
        {
            MetaStoreDataContext dc = new MetaStoreDataContext(_metaStoreConnectionString);
            SubService subService = (from s in dc.SubServices
                                        where s.SubServiceID == ssID
                                        select s).First();
            dc.Dispose();
            SubServiceMetadataModel subMetaModel = new SubServiceMetadataModel()
            {
                SubServiceID            = subService.SubServiceID.ToString(),
                SubServiceName          = subService.SubServiceName,
                SubServiceDescription   = subService.SubServiceDescription,
                UniqueURN               = subService.UniqeURN,
                NumberOfInstances       = subService.NumberOfInstances
            };
            return subMetaModel;
        }

        internal static SubServiceInstanceModel GetSubServiceInstance(Guid ssID)
        {
            MetaStoreDataContext dc = new MetaStoreDataContext(_metaStoreConnectionString);

            SubService subService = (from s in dc.SubServices
                                     where s.SubServiceID == ssID
                                     select s).First();
            SubServiceRunConfig subServiceRunConfig = (from s in dc.SubServiceRunConfigs
                                     where s.SubServiceRunConfigID == subService.SubServiceRunConfigID
                                     select s).First();
            string version       = (from d in dc.Dependencies
                                    where d.SubServiceID == ssID
                                    select d.Version ).First();             
            dc.Dispose();

            SubServiceMetadataModel subMetaModel = new SubServiceMetadataModel()
            {
                SubServiceID = subService.SubServiceID.ToString(),
                SubServiceName = subService.SubServiceName,
                SubServiceDescription = subService.SubServiceDescription,
                UniqueURN = subService.UniqeURN,
                NumberOfInstances = subService.NumberOfInstances
            };

            RunConfigModel configInst = new RunConfigModel()
            {
                RunConfig = subServiceRunConfig.RunConfig,
                RunMode   = ReadOnlyDataCollection.StartModes.Where(mode=>mode.Code == subServiceRunConfig.RunMode).First().Name
            };

            SubServiceInstanceModel subInst = new SubServiceInstanceModel()
            {
                Params = String.Empty,
                SubService = subMetaModel,
                UniqueURN = subMetaModel.UniqueURN,
                Version = version,
                SubServiceRunConfig = configInst
            };

            return subInst;
        }

        internal static void CreateSubServiceInstance(SubServiceInstanceModel model)
        {
            MetaStoreDataContext dc = new MetaStoreDataContext(_metaStoreConnectionString);

            SubServiceRunConfig config      = new SubServiceRunConfig();
            config.SubServiceRunConfigID    = Guid.NewGuid();
            config.CreatedBy                = Guid.Empty;
            config.CreatedOn                = DateTime.Now;
            config.IsMasterRunConfig        = false;
            config.RunMode                  = ReadOnlyDataCollection.StartModes.Where((mode) => mode.Name == model.SubServiceRunConfig.RunMode).First().Code;
            config.RunConfig = model.SubServiceRunConfig.RunConfig == null ? string.Empty : model.SubServiceRunConfig.RunConfig;
            dc.SubServiceRunConfigs.InsertOnSubmit(config);

            SubServiceInstance inst = new SubServiceInstance()
            {
                AssociatedIdentityID    = Guid.Empty,
                CreatedBy               = Guid.Empty,
                CreatedOn               = DateTime.Now,
                Params                  = model.Params,
                UniqeURN                = model.UniqueURN,
                Version                 = model.Version,
                SubServiceInstanceID    = Guid.NewGuid(),
                SubServiceID            = new Guid(model.SubService.SubServiceID),
                SubServiceRunConfigID   = config.SubServiceRunConfigID
            };
            dc.SubServiceInstances.InsertOnSubmit(inst);

            var subService = (from s in dc.SubServices
                                     where s.SubServiceID == new Guid(model.SubService.SubServiceID)
                                     select s).Single();

            subService.NumberOfInstances += 1;

            dc.SubmitChanges();
            dc.Dispose();
        }

        internal static ActivityLogModel[] GetActivityLog()
        {
            MessageBoxDataContext msgBxDC = new MessageBoxDataContext(_messageBoxConnectionString);
            ActivityLogModel[] logs = (from e in msgBxDC.EventLogs
                                       select (new ActivityLogModel { EventType = e.EventType, EventMessage = e.EventMessage, EventDetails = e.EventDetails, CreatedOn = e.CreatedOn })).Take(200).ToArray();
            return logs;
        }
    }
}